home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Camelot
/
Camelot 134 (1991-10)(Swedish User Group of Amiga)(SE)(PD)[WB].zip
/
Camelot 134 (1991-10)(Swedish User Group of Amiga)(SE)(PD)[WB].adf
/
GIFMachine
/
Sources
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-01
|
11KB
|
512 lines
/* Copyright 1990 by Christopher A. Wichura.
See file GIFMachine.doc for full description of rights.
*/
#include "GIFMachine.h"
#include <dos/rdargs.h>
#include <dos/dosasl.h>
#include <dos/stdio.h>
#include <workbench/startup.h>
struct GIFdescriptor gdesc;
struct RGB **BitPlane;
struct RGB GlobalColourTable[256];
extern UWORD *SHAMmem;
extern BYTE *PlaneBuf;
extern BOOL Laced;
extern UBYTE *Planes[24];
ULONG ImageNumber;
extern struct MinList CommentList;
/* indicates which memory list to allocate from */
extern UWORD CurrentMem;
/* the current GIF file handle */
BPTR GIFfh = NULL;
/* flag: display line counts during conversion or not */
BOOL DisplayCounts;
/* here we have some defines relating to our GADS call */
#define ESC "\x1B["
#define GIFMACH ESC "1;33;42mGIFMachine" ESC "0;32;40m"
#define ARG_TEMPLATE "GIFfiles/A/M,TO/K,ALL/S,NOBORDER/N/K,XCOMP/S,DITHER/S,XFLIP/S,YFLIP/S,DEEP/S,NOCOUNT/S,BUFSIZE/N/K"
enum ReadArgs {
ARG_FILES,
ARG_TO,
ARG_ALL,
ARG_NOBORD,
ARG_XCOMP,
ARG_DITHER,
ARG_FLIPX,
ARG_FLIPY,
ARG_DEEP,
ARG_NOCOUNT,
ARG_BUFSIZ,
ARG_sizeof
};
/* we will make the argument array global so that other modules can get at
the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
struct RDArgs *ArgsPtr;
char *ArgArray[ARG_sizeof];
BOOL ArgToIsDir;
/* size of the read buffered i/o space */
static ULONG BufSize = 2048; /* default size is 2k */
int NoBorderLineThresh = 0;
/* some mem pointers used when we do dithering */
BYTE *CurrentLineErr[3];
BYTE *LastLineErr[3];
/* this flag says if we scaled the image */
BOOL DidXComp;
/* we print this when the user hits the break key */
char *AbortMsg = "*** User Interruption!\n";
/* storage for our library bases */
struct Library *MathIeeeDoubBasBase = NULL;
struct Library *IFFParseBase = NULL;
struct Library *GfxBase = NULL;
/* storage for our anchor when looking for pattern matches */
struct Anchor {
struct AnchorPath APath;
char Path[256];
} *anchor = NULL;
/* here we have our main routine */
int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
{
register char **FilesPtr;
struct RDArgs MyArgs;
extern UBYTE __far arg_help[];
extern UBYTE __far VersionID[];
InitMemory();
if (WBMsg) {
WarnMustUseCLI();
MyExit(5);
}
if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))) {
MyPrintf("Unable to access %s!\n", "graphics.library");
MyExit(5);
}
if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
MyExit(5);
}
if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
MyPrintf("Unable to access %s!\n", "iffparse.library");
MyExit(5);
}
memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(arg_help) + (2 * strlen(GIFMACH)) + strlen(VersionID) + 1))) {
PutStr("Out of memory!\n");
MyExit(5);
}
MySPrintf((char *)MyArgs.RDA_ExtHelp, arg_help, GIFMACH, VersionID, GIFMACH);
if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
PrintFault(IoErr(), NULL);
MyExit(5);
}
MyFree((char *)MyArgs.RDA_ExtHelp);
if (ArgArray[ARG_TO])
ArgToIsDir = IsDir(ArgArray[ARG_TO]);
if (ArgArray[ARG_NOBORD]) {
NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
PutStr("Invalid NOBORDER line threshhold specified.\n");
MyExit(3);
}
}
if (ArgArray[ARG_NOCOUNT])
DisplayCounts = FALSE;
else
DisplayCounts = TRUE;
if (ArgArray[ARG_BUFSIZ])
BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
PutStr("No GIF files selected.\n");
MyExit(3);
}
InitDiff(); /* one time init for the RGBdiff function */
while (*FilesPtr)
DoPattern(*FilesPtr++);
MyExit(0);
}
void MyExit(ULONG result)
{
if (GIFfh)
Close(GIFfh);
if (IFFParseBase)
CloseLibrary(IFFParseBase);
if (MathIeeeDoubBasBase)
CloseLibrary(MathIeeeDoubBasBase);
if (GfxBase)
CloseLibrary(GfxBase);
if (anchor)
MatchEnd(&anchor->APath);
if (ArgsPtr)
FreeArgs(ArgsPtr);
FreeAll(1);
FreeAll(0);
XCEXIT(result);
}
/* this will walk through a pattern doing conversions */
void DoPattern(char *pat)
{
register int error;
if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
PutStr("Out of memory!\n");
MyExit(10);
}
anchor->APath.ap_Strlen = sizeof(anchor->Path);
anchor->APath.ap_Flags = APF_DOWILD;
anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
error = MatchFirst(pat, &anchor->APath);
while (!error) {
if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
if (ArgArray[ARG_ALL]) {
if (!(anchor->APath.ap_Flags & APF_DIDDIR))
anchor->APath.ap_Flags |= APF_DODIR;
anchor->APath.ap_Flags &= ~APF_DIDDIR;
}
} else
Convert(anchor->APath.ap_Buf);
error = MatchNext(&anchor->APath);
}
MatchEnd(&anchor->APath);
MyFree((char *)anchor);
anchor = NULL;
switch(error) {
case ERROR_BREAK:
PutStr(AbortMsg);
MyExit(ABORTEXITVAL);
break;
case ERROR_OBJECT_NOT_FOUND:
PutStr("File not found.\n");
break;
case ERROR_BUFFER_OVERFLOW:
PutStr("Path too long!\n");
break;
case ERROR_NO_MORE_ENTRIES: /* normal termination */
break;
default:
MyPrintf("I/O Error #%ld!\n", error);
break;
}
}
/* here we have the routine that gets ready to do the conversion */
void Convert(char *name)
{
register int index;
char *basename;
char *ptr;
char sig[7];
int size;
int error;
int colours;
LONG cmdcode;
struct DateStamp StartTime, EndTime;
CurrentMem++;
if (!(GIFfh = Open(name, MODE_OLDFILE))) {
MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
goto LeaveConvert;
}
SetVBuf(GIFfh, NULL, BUF_FULL, BufSize);
sig[6] = NULL;
if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
MyPrintf("%s is not a GIF file...\n", name);
goto LeaveConvert;
}
MyPrintf("Converting %s ", name);
basename = FilePart(name);
ptr = basename + strlen(basename) - 4;
if (!strnicmp(".gif", ptr, 4))
*ptr = NULL;
size = strlen(basename) + 6;
if (ArgArray[ARG_TO]) {
if (ArgToIsDir)
size += strlen(ArgArray[ARG_TO]) + 1;
else
size = strlen(ArgArray[ARG_TO]) + 1;
}
if (!(ptr = MyAlloc(size))) {
PutStr("... Out of memory!\n");
goto LeaveConvert;
}
if (ArgArray[ARG_TO]) {
strcpy(ptr, ArgArray[ARG_TO]);
if (ArgToIsDir) {
AddPart(ptr, basename, size);
strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
}
} else {
strcpy(ptr, basename);
strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
}
MyPrintf("to %s...\n", ptr);
DateStamp(&StartTime);
if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
PutStr("Error reading screen descriptor.\n");
goto LeaveConvert;
}
FlipWord(&gdesc.gd_Width);
FlipWord(&gdesc.gd_Height);
MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
sig, gdesc.gd_Width, gdesc.gd_Height);
NewList((struct List *)&CommentList);
DidXComp = 0;
colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
if (!(gdesc.gd_ColInfo & 1L << 7)) {
PutStr("No global colour map supplied, using internal.\n");
for (index = 0; index < colours; index++) {
GlobalColourTable[index].rgb_Red =
GlobalColourTable[index].rgb_Green =
GlobalColourTable[index].rgb_Blue = index;
}
} else {
MyPrintf("Global colour map contains %ld entries.\n", colours);
for (index = 0; index < colours; index++) {
if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
MyPrintf("Error reading global colour #%ld.\n",
index);
goto LeaveConvert;
}
}
}
size = ((gdesc.gd_Width + 7) / 8) + 1;
size += (size + 127) >> 7;
if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
!(SHAMmem = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
!(PlaneBuf = (BYTE *)MyAlloc(size))) {
PutStr("Out of memory trying to allocate picture.\n");
goto LeaveConvert;
}
size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
for (index = 0; index < gdesc.gd_Height; index++)
if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
PutStr("Out of memory trying to allocate picture.\n");
goto LeaveConvert;
}
size = ((gdesc.gd_Width + 7) / 8) + 1;
for (index = 0; index < (ArgArray[ARG_DEEP] ? 24 : 6); index++)
if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
PutStr("Out of memory trying to allocate picture.\n");
goto LeaveConvert;
}
if (ArgArray[ARG_DITHER]) {
size = gdesc.gd_Width * sizeof(BYTE);
for (index = 0; index < 3; index++)
if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
!(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
PutStr("Out of memory trying to allocate picture.\n");
goto LeaveConvert;
}
}
ImageNumber = 1;
/* at this point we start looking for images, extensions or the gif
terminator. we call the appropriate routine as we find each. */
for (error = FALSE; error == FALSE;) {
if ((cmdcode = FGetC(GIFfh)) == -1) {
PutStr("...I/O error reading GIF file.\n");
goto LeaveConvert;
}
switch(cmdcode) {
case GIF_IMAGE:
error = DoImage(GIFfh);
break;
case GIF_EXTENSION:
error = DoExtension(GIFfh);
break;
case GIF_TERMINATOR:
if (ArgArray[ARG_NOBORD])
StripBorder();
if (ArgArray[ARG_FLIPX])
DoXFlip();
if (ArgArray[ARG_FLIPY])
DoYFlip();
if (ArgArray[ARG_XCOMP]) {
DoXComp();
DidXComp = 1;
}
if (gdesc.gd_Height > 200 && DidXComp)
Laced = TRUE;
else
Laced = FALSE;
if (!ArgArray[ARG_DEEP]) {
if (ArgArray[ARG_DITHER])
DitherTo12();
else
ReduceTo12();
GIFtoSHAM();
}
error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
break;
default:
MyPrintf("...Unknown directive #%ld encountered.\n",
cmdcode);
error = TRUE;
}
}
DateStamp(&EndTime);
{
register ULONG Hours;
register ULONG Minutes;
register ULONG Seconds;
register ULONG Seconds2;
Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
Seconds -= Seconds2;
Hours = Seconds / 3600;
Seconds -= Hours * 3600;
Minutes = Seconds / 60;
Seconds -= Minutes * 60;
MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
Hours, (Hours != 1 ? "s" : ""),
Minutes, (Minutes != 1 ? "s" : ""),
Seconds, (Seconds != 1 ? "s" : ""));
}
LeaveConvert:
FreeAll(CurrentMem--);
if (GIFfh) {
Close(GIFfh);
GIFfh = NULL;
}
}
/* this will check to see if we have a directory or not */
BOOL IsDir(char *name)
{
register BPTR lock;
register BOOL result = FALSE;
struct FileInfoBlock __aligned fib;
if (lock = Lock(name, ACCESS_READ)) {
if (Examine(lock, &fib)) {
if (fib.fib_DirEntryType > 0)
result = TRUE;
}
UnLock(lock);
}
return result;
}
/* this will convert a word from LSB/MSB to MSB/LSB */
void FlipWord(UWORD *word)
{
register UBYTE swap1;
register UBYTE swap2;
swap1 = *word & 0xFF;
swap2 = (*word & 0xFF00) >> 8;
*word = swap1 << 8 | swap2;
}